<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:cache="http://www.springframework.org/schema/cache"
	   xmlns:p="http://www.springframework.org/schema/p"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
       		http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
       		http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache.xsd">

	<cache:advice id="cacheAdviceInterface" cache-manager="cacheManager">
		<cache:caching cache="testCache">
			<cache:cacheable method="cache"/>
			<cache:cacheable method="cacheNull"/>
			<cache:cacheable method="cacheSync" sync="true"/>
			<cache:cacheable method="cacheSyncNull" sync="true"/>
			<cache:cacheable method="conditional" condition="#classField == 3"/>
			<cache:cacheable method="conditionalSync" sync="true" condition="#classField == 3"/>
			<cache:cacheable method="unless" unless="#result > 10"/>
			<cache:cacheable method="key" key="#p0"/>
			<cache:cacheable method="varArgsKey"/>
			<cache:cacheable method="nam*" key="#root.methodName"/>
			<cache:cacheable method="rootVars" key="#root.methodName + #root.method.name + #root.targetClass + #root.target"/>
			<cache:cacheable method="customKeyGenerator" key-generator="customKeyGenerator"/>
			<cache:cacheable method="unknownCustomKeyGenerator" key-generator="unknownBeanName"/>
			<cache:cacheable method="customCacheManager" cache-manager="customCacheManager"/>
			<cache:cacheable method="unknownCustomCacheManager" cache-manager="unknownBeanName"/>
			<cache:cacheable method="nullValue" cache="testCache"/>
		</cache:caching>
		<cache:caching>
			<cache:cache-evict method="evict" key="#p0" cache="testCache"/>
			<cache:cache-evict method="evictWithException" cache="testCache"/>
			<cache:cache-evict method="evictEarly" cache="testCache" before-invocation="true"/>
			<cache:cache-evict method="evictAll" cache="testCache" all-entries="true"/>
			<cache:cache-evict method="evictAllEarly" cache="testCache" all-entries="true" before-invocation="true"/>
		</cache:caching>
		<cache:caching cache="testCache">
			<cache:cache-put method="update"/>
			<cache:cache-put method="conditionalUpdate" condition="#arg.equals(3)"/>
		</cache:caching>
		<cache:caching method="mult*Cache">
			<cache:cacheable cache="primary"/>
			<cache:cacheable cache="secondary"/>
		</cache:caching>
		<cache:caching method="multiEvict">
			<cache:cache-evict cache="primary"/>
			<cache:cache-evict cache="primary" key="#p0 + 'A'"/>
			<cache:cache-evict method="multiEvict" cache="secondary" key="#p0"/>
		</cache:caching>
		<cache:caching>
			<cache:cacheable method="multiCacheAndEvict" cache="primary" key="#root.methodName"/>
			<cache:cache-evict method="multiCacheAndEvict" cache="secondary"/>
			<cache:cacheable method="multiConditionalCacheAndEvict" cache="primary" condition="#p0 == 3"/>
			<cache:cache-evict method="multiConditionalCacheAndEvict" cache="secondary"/>
			<cache:cache-put method="multiUpdate" cache="primary"/>
			<cache:cache-put method="multiUpdate" cache="secondary"/>
			<cache:cache-put method="putRefersToResult" cache="primary" key="#result.id"/>
			<cache:cache-put method="putEvaluatesUnlessBeforeKey" cache="primary" key="#result.id" unless="#result == null"/>
		</cache:caching>
	</cache:advice>

	<cache:advice id="cacheAdviceClass" cache-manager="cacheManager" key-generator="keyGenerator">
		<cache:caching cache="testCache">
			<cache:cacheable method="key" key="#p0"/>
			<cache:cacheable method="varArgsKey"/>
			<cache:cacheable method="nam*" key="#root.methodName + #root.caches[0].name"/>
			<cache:cacheable method="rootVars" key="#root.methodName + #root.method.name + #root.targetClass + #root.target"/>
			<cache:cacheable method="cache"/>
			<cache:cacheable method="conditional"/>
			<cache:cacheable method="unless"/>
			<cache:cacheable method="null*"/>
		</cache:caching>
		<cache:caching>
			<cache:cache-evict method="invalidate" cache="testCache"/>
			<cache:cache-evict method="evict" key="#p0" cache="testCache"/>
			<cache:cache-evict method="evictWithException" cache="testCache"/>
			<cache:cache-evict method="evictEarly" cache="testCache" before-invocation="true"/>
			<cache:cache-evict method="invalidateEarly" key="#p0" cache="testCache" before-invocation="true"/>
			<cache:cache-evict method="evictAll" cache="testCache" all-entries="true"/>
		</cache:caching>
		<cache:caching cache="testCache">
			<cache:cache-put method="update"/>
			<cache:cache-put method="conditionalUpdate" condition="#arg.equals(3)"/>
		</cache:caching>
		<cache:caching>
			<cache:cacheable method="multiCache" cache="primary"/>
			<cache:cacheable method="multiCache" cache="secondary"/>
			<cache:cache-evict method="multiEvict" cache="primary"/>
			<cache:cache-evict method="multiEvict" cache="secondary" key="#p0"/>
			<cache:cache-evict method="multiEvict" cache="primary" key="#p0 + 'A'"/>
			<cache:cacheable method="multiCacheAndEvict" cache="primary" key="#root.methodName"/>
			<cache:cache-evict method="multiCacheAndEvict" cache="secondary"/>
			<cache:cacheable method="multiConditionalCacheAndEvict" cache="primary" condition="#p0 == 3"/>
			<cache:cache-evict method="multiConditionalCacheAndEvict" cache="secondary"/>
			<cache:cache-put method="multiUpdate" cache="primary"/>
			<cache:cache-put method="multiUpdate" cache="secondary"/>
			<cache:cache-put method="putRefersToResult" cache="primary" key="#result.id"/>
			<cache:cache-put method="putEvaluatesUnlessBeforeKey" cache="primary" key="#result.id" unless="#result == null"/>
		</cache:caching>
	</cache:advice>

	<aop:config>
		<aop:advisor advice-ref="cacheAdviceInterface" pointcut="execution(* *..DefaultCacheableService.*(..))" order="1"/>
		<aop:advisor advice-ref="cacheAdviceClass" pointcut="execution(* *..AnnotatedClassCacheableService.*(..))" order="1"/>
		<aop:advisor advice-ref="debugInterceptor" pointcut="execution(* *..CacheableService.*(..))" order="2"/>
	</aop:config>

	<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="testCache"/>
				<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="primary"/>
				<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="secondary"/>
			</set>
		</property>
	</bean>

	<bean id="keyGenerator" class="org.springframework.context.testfixture.cache.SomeKeyGenerator"/>

    <bean id="customKeyGenerator" class="org.springframework.context.testfixture.cache.SomeCustomKeyGenerator"/>

	<bean id="customCacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="testCache"/>
			</set>
		</property>
	</bean>

	<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>

	<bean id="service" class="org.springframework.context.testfixture.cache.beans.DefaultCacheableService"/>

	<bean id="classService" class="org.springframework.context.testfixture.cache.beans.AnnotatedClassCacheableService"/>
</beans>
